
//
//  BluetoothManager.m
//  BluetoothProject
//
//  Created by JianWei Chen on 16/9/5.
//  Copyright © 2016年 JianWei Chen. All rights reserved.
//

#import "BabyBluetooth.h"
#import "DTCBluetoothManager.h"
#import "DTCBluetoothDataHandle.h"
#import "DTCDeviceModel.h"
#import "DTCBluetoothConfig.h"

@interface DTCBluetoothManager()

@property (nonatomic, assign) BOOL scanDevice;//是否开启搜索周围设备
@property(strong, nonatomic) BabyBluetooth *babyBluetooth;//蓝牙管理类
@property(strong, nonatomic) NSTimer *scanTimer;

@end
@implementation DTCBluetoothManager

#pragma mark - 初始化
+(instancetype)shareInstance
{
    static DTCBluetoothManager *static_manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        static_manager = [[DTCBluetoothManager alloc]init];
        
        static_manager.babyBluetooth = [BabyBluetooth  shareBabyBluetooth];
        static_manager.scanDeviceList = [NSMutableArray array];
        static_manager.connectedDeviceList = [NSMutableArray array];
        static_manager.scanTimer=[NSTimer scheduledTimerWithTimeInterval:7.f target:static_manager selector:@selector(searchAndCheckCBperipherals) userInfo:nil repeats:YES];
        [static_manager babyDelegate];
    });
    return static_manager;
}

#pragma mark - 事件处理
/*
 读写方法
 */
- (void)writeValueToDevice:(DTCDeviceModel *)device writeData:(NSData *)data characteristicValue:(NSString *)characterValue
{
    CBPeripheral *sender = device.currentPeripheral;
    if (sender) {
        if (sender.state == CBPeripheralStateConnected) {
            for (int i = 0; i < sender.services.count; i++) {
                CBService *service = [sender.services objectAtIndex:i];
                for (int j = 0; j < service.characteristics.count; j++) {
                    CBCharacteristic *characteristic = [service.characteristics objectAtIndex:j];
                    if([characteristic.UUID.UUIDString isEqualToString:characterValue]){
                        
                        [self writeValue:sender andChare:characteristic anddata:data];
                        
                    }
                }
            }
        }else{
            BluetoothNoticeNSLog(@"外设write失败，设备处理未连接状态");
        }
    }else{
        BluetoothNoticeNSLog(@"外设write失败，没有对应的外设影响");
    }
}

- (void)writeValue:(CBPeripheral *)per andChare:(CBCharacteristic *)chara anddata:(NSData *)data
{
    if (data.length == 0) {
        return;
    }
    //当发送指令，设备没反馈的时候，多注意下特征值类型，并切换发送方式
    CBCharacteristicWriteType type = CBCharacteristicWriteWithResponse;
    if (data.length > 20) {
        for (int i = 0; i < data.length; i+= 20) {
            [per writeValue:[data subdataWithRange:NSMakeRange(i, 20)] forCharacteristic:chara type:type];
            
            int index = i + 20;
            
            if (data.length - index > 0 && data.length - index < 20) {
                [per writeValue:[data subdataWithRange:NSMakeRange(index, data.length - index)] forCharacteristic:chara type:type];
            }
        }
    }else{
        [per writeValue:data forCharacteristic:chara type:type];
    }
}

- (void)readValueFromDevice:(DTCDeviceModel *)device characteristicValue:(NSString *)characterValue
{
    CBPeripheral *sender = device.currentPeripheral;
    if (sender) {
        for (int i = 0; i < sender.services.count; i++) {
            CBService *service = [sender.services objectAtIndex:i];
            
            if ([service.UUID.UUIDString isEqualToString:@"FFE0"]) {
                for (int j = 0; j < service.characteristics.count; j++) {
                    CBCharacteristic *characteristic = [service.characteristics objectAtIndex:j];
                    if ([characteristic.UUID.UUIDString isEqualToString:@"FFE1"]) {
                        [sender readValueForCharacteristic:characteristic];
                    }
                }
            }
        }
    }else{
        BluetoothNoticeNSLog(@"外设read失败，没有对应的外设影响");
    }
}

/*
 蓝牙设备操作
 */
- (void)connectDevice:(DTCDeviceModel *)device
{
    if(device.currentPeripheral){
        _babyBluetooth.having(device.currentPeripheral).and.channel(@"peripheralView").then.connectToPeripherals().discoverServices().discoverCharacteristics().readValueForCharacteristic().discoverDescriptorsForCharacteristic().readValueForDescriptors().begin();
        
        BluetoothConnectDTNSLog(@"开始对外设:%@ 外设UUID %@ 发起连接",device.currentPeripheral.name,device.currentPeripheral.identifier.UUIDString);
    }else{
        for (DTCDeviceModel *deviceModel in _scanDeviceList) {
            if ([deviceModel.mac.lowercaseString isEqualToString:deviceModel.mac.lowercaseString]) {
                _babyBluetooth.having(deviceModel.currentPeripheral).and.channel(@"peripheralView").then.connectToPeripherals().discoverServices().discoverCharacteristics().readValueForCharacteristic().discoverDescriptorsForCharacteristic().readValueForDescriptors().begin();
                BluetoothConnectDTNSLog(@"开始对外设:%@ 外设UUID %@ 发起连接",deviceModel.currentPeripheral.name,deviceModel.currentPeripheral.identifier.UUIDString);
                return;
            }
        }
        BluetoothNoticeNSLog(@"该对象不存在映射的外设");
    }
}

- (void)disconnectDevice:(DTCDeviceModel *)device
{
    if(device.currentPeripheral){
        [_babyBluetooth cancelPeripheralConnection:device.currentPeripheral];
    }
}


/*
 蓝牙管理操作
 */
- (void)scanAroundDevice
{
    self.scanDevice = YES;
    [self updateScanDeviceStatus];
}

- (void)cancelScanDevice
{
    self.scanDevice = NO;
    [self updateScanDeviceStatus];
}

- (void)cancelAllDeviceConnection
{
    [_babyBluetooth cancelAllPeripheralsConnection];
}

- (DTCDeviceModel *)getCurrentConnectedDevicce
{
    if (self.connectedDeviceList.count == 0) {
        return nil;
    }
    return [self.connectedDeviceList firstObject];
}

/*
 设置设备过滤条件
 */
- (void)setFilterDeviceByServiceUUID:(NSArray *)serviceList onDiscoverPeripherals:(BOOL (^)(NSString *peripheralName, NSDictionary *advertisementData, NSNumber *RSSI))filter
{
    //根据周围扫描到的外设广播内容进行过滤
    [_babyBluetooth setFilterOnDiscoverPeripherals:^BOOL(NSString *peripheralName, NSDictionary *advertisementData, NSNumber *RSSI) {

        BOOL discoverStatus = YES;
        if (filter != nil) {
            discoverStatus = filter(peripheralName,advertisementData,RSSI);
        }
        return discoverStatus;
    }];
    
    //搜索条件过滤
    NSDictionary *scanForPeripheralsWithOptions = @{CBCentralManagerScanOptionAllowDuplicatesKey:@(YES)};
    //设备服务过滤，
    if (serviceList.count == 0) {
        [_babyBluetooth setBabyOptionsWithScanForPeripheralsWithOptions:scanForPeripheralsWithOptions connectPeripheralWithOptions:nil scanForPeripheralsWithServices:nil discoverWithServices:nil discoverWithCharacteristics:nil];
    }else{
        NSMutableArray *serviceUUIDList = [[NSMutableArray alloc]init];
        for (NSString *serviceUUID in serviceList) {
            [serviceUUIDList addObject:[CBUUID UUIDWithString:serviceUUID]];
        }
        [_babyBluetooth setBabyOptionsWithScanForPeripheralsWithOptions:scanForPeripheralsWithOptions connectPeripheralWithOptions:nil scanForPeripheralsWithServices:serviceUUIDList discoverWithServices:nil discoverWithCharacteristics:nil];
    }
}

- (void)setWriteNotifyCharacteristicValue:(NSArray *)characteristicValueList
{
    if (characteristicValueList.count == 0) {
        return;
    }
    __weak typeof(self) weakSelf = self;
    [_babyBluetooth setBlockOnDiscoverCharacteristics:^(CBPeripheral *peripheral, CBService *service, NSError *error) {
        for (CBCharacteristic *characteristic in service.characteristics) {
            BluetoothConnectDTNSLog(@"搜索到设备：%@ 设备service为:%@ 服务的CBCharacteristic为:%@",[weakSelf getDeviceModelByPeripheral:peripheral].customName,service.UUID.UUIDString,characteristic.UUID.UUIDString);
            [weakSelf deviceFindCharacteristic:[weakSelf getDeviceModelByPeripheral:peripheral] characeristic:characteristic error:error];
            
            for (NSString *character in characteristicValueList) {
                
                if ([characteristic.UUID.UUIDString isEqualToString:character]){
                    [weakSelf.babyBluetooth notify:peripheral characteristic:characteristic block:^(CBPeripheral *peripheral, CBCharacteristic *characteristics, NSError *error) {
                        NSString *value = [NSString convertDataToHexStr:characteristics.value];
                        BluetoothAssistNoticeNSLog(@"********* ********* ***********");
                        BluetoothNoticeNSLog(@"-- >设备:%@ write回复:%@",[weakSelf getDeviceModelByPeripheral:peripheral].customName,value);
                        BluetoothAssistNoticeNSLog(@"********* ********* ***********");
                        
                        [weakSelf sendDataByWriteData:characteristic.value andNotifyCharacteristic:characteristic.UUID.UUIDString andDevice:[weakSelf getDeviceModelByPeripheral:peripheral]];
                    }];
                }
            }
        }
    }];
}

- (void)setReadNotifyCharacteristicValue:(NSArray *)characteristicValueList
{
    if (characteristicValueList.count) {
        return;
    }
    __weak typeof(self) weakSelf = self;
    //设置读取characteristics的委托
    [_babyBluetooth setBlockOnReadValueForCharacteristic:^(CBPeripheral *peripheral, CBCharacteristic *characteristics, NSError *error) {
        for (NSString *characterString in characteristicValueList) {
            if ([characteristics.UUID.UUIDString isEqualToString:characterString]) {
                MAIN(^{
                    NSString *value = [NSString convertDataToHexStr:characteristics.value];
                    BluetoothAssistNoticeNSLog(@"********* ********* ***********");
                    BluetoothNoticeNSLog(@"--> 设备:%@ read回复:%@",[weakSelf getDeviceModelByPeripheral:peripheral].customName,value);
                    BluetoothAssistNoticeNSLog(@"********* ********* ***********");
                    [weakSelf sendDataByReadData:characteristics.value andNotifyCharacteristic:characteristics.UUID.UUIDString andDevice:[weakSelf getDeviceModelByPeripheral:peripheral]];
                });
            }
        }
    }];
}
#pragma mark -蓝牙配置和操作

/**
 处理蓝牙设备搜索，并当在20秒内没有重复搜索到的时候移除
 */
- (void)searchAndCheckCBperipherals
{
    for (NSUInteger i = 0; i < self.connectedDeviceList.count; i++){
        
        DTCDeviceModel *device = self.connectedDeviceList[i];
        device.scanTime = time(NULL);
    }
    
    for (NSUInteger i=0 ; i < self.scanDeviceList.count; i++) {
        
        DTCDeviceModel *device = self.scanDeviceList[i];
        if ((time(NULL)-device.scanTime) > 20 && ![self.connectedDeviceList containsObject:device]) {
            [self.scanDeviceList removeObject:device];
            [self udpateDeviceCount];
        }
    }
}

- (NSString*)hexStringForData:(NSData*)data
{
    if (data == nil) {
        return nil;
    }
    NSString *str = [NSString convertDataToHexStr:data];
    if (str.length < 12) {
        return @"";
    }
    return [str substringWithRange:NSMakeRange(str.length - 12, 12)];
}

/*
 更新蓝牙中心状态
 */
- (void)updateCentralManagerStateHandle
{
    __weak typeof(self) weakSelf = self;
    [_babyBluetooth setBlockOnCentralManagerDidUpdateState:^(CBCentralManager *central) {
        
        weakSelf.blueState = central.state;
        [weakSelf updateCentralManagerState:central.state];
        
        if (central.state == CBCentralManagerStatePoweredOn) {
            MAIN(^{
                [weakSelf updateScanDeviceStatus];
                [weakSelf.scanTimer setFireDate:[NSDate distantPast]];
            });
        }else{
            MAIN(^{
                [weakSelf.scanTimer setFireDate:[NSDate distantFuture]];
                [weakSelf.scanDeviceList removeAllObjects];
                [weakSelf.connectedDeviceList removeAllObjects];
                [weakSelf udpateDeviceCount];
            });
        }
    }];
}

/*
 扫描到外设以后
 */
- (void)managerDiscoverPeripheralsHandle
{
    __weak typeof(self) weakSelf = self;
    [_babyBluetooth setBlockOnDiscoverToPeripherals:^(CBCentralManager *central, CBPeripheral *peripheral, NSDictionary *advertisementData, NSNumber *RSSI) {
        
        BOOL isExist = [weakSelf comparePeripheralisEqual:peripheral RSSI:RSSI];
        if (!isExist && [advertisementData[@"kCBAdvDataLocalName"]length] != 0) {
            
            NSLog(@"advertisementData = %@ ,peripheral = %@",advertisementData,peripheral);
            
            DTCDeviceModel *device = [[DTCDeviceModel alloc]init];
            device.mac = [weakSelf hexStringForData:[advertisementData objectForKey:@"kCBAdvDataManufacturerData"]];
            if (device.mac.length == 0 && peripheral.identifier.UUIDString.length >= 12) {
                device.mac = [peripheral.identifier.UUIDString substringWithRange:NSMakeRange(peripheral.identifier.UUIDString.length - 12, 12)];
            }
            device.localName = peripheral.name;
            device.customName = peripheral.name;
            device.currentPeripheral = peripheral;
            device.peripheralRSSI = RSSI;
            device.scanTime=time(NULL);
            device.peripheralUUID = peripheral.identifier.UUIDString;
            
            [weakSelf.scanDeviceList addObject:device];
            [weakSelf udpateDeviceCount];
        }
    }];
}

/*
 连接设备过程中，外设发现和特征发现
 */
- (void)connectToDeviceHandle
{
    BabyRhythm *rhythm = [[BabyRhythm alloc]init];
    __weak typeof(self) weakSelf = self;
    [_babyBluetooth setBlockOnDiscoverServices:^(CBPeripheral *peripheral, NSError *error) {
        for (CBService *service in peripheral.services) {
            BluetoothConnectDTNSLog(@"搜索到设备：%@ 设备service为:%@",[weakSelf getDeviceModelByPeripheral:peripheral].customName,service.UUID.UUIDString);
        }
        if (error) {
            NSLog(@"%@",error.description);
        }
        
        [rhythm beats];
    }];
    //设置发现characteristics的descriptors的委托
    [_babyBluetooth setBlockOnDiscoverDescriptorsForCharacteristic:^(CBPeripheral *peripheral, CBCharacteristic *characteristic, NSError *error) {
    }];
    
    [_babyBluetooth setBlockOnDiscoverDescriptorsForCharacteristic:^(CBPeripheral *peripheral, CBCharacteristic *characteristic, NSError *error) {
    }];
}

/*
 设备连接成功以后
 */
- (void)connectDeviceSuccessHandle
{
    __weak typeof(self) weakSelf = self;
    
    [_babyBluetooth setBlockOnConnected:^(CBCentralManager *central, CBPeripheral *peripheral) {
        
        for (NSInteger i = 0; i < weakSelf.scanDeviceList.count; i++) {
            
            DTCDeviceModel *device = weakSelf.scanDeviceList[i];
            if ([device.currentPeripheral isEqual:peripheral]) {
                if (![weakSelf.connectedDeviceList containsObject:device]) {
                    [weakSelf.connectedDeviceList addObject:device];
                }
                MAIN(^{
                    [weakSelf deviceHasConnect:device];
                });
            }
        }
        //连接反馈
        BluetoothAssistNoticeNSLog(@"||||||||| ||||||||| |||||||||||");
        BluetoothNoticeNSLog(@"连接设备:%@成功 外设的UUID:%@",[weakSelf getDeviceModelByPeripheral:peripheral].customName,peripheral.identifier.UUIDString);
        BluetoothAssistNoticeNSLog(@"||||||||| ||||||||| |||||||||||");
    }];
}

/*
 设备断开连接
 */
- (void)disconnectDeviceSuccessHandle
{
    __weak typeof(self) weakSelf = self;
    
    [_babyBluetooth setBlockOnDisconnect:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
        BluetoothNoticeNSLog(@"设备:%@连接断开 外设的UUID:%@",[weakSelf getDeviceModelByPeripheral:peripheral].customName,peripheral.identifier.UUIDString);
        BluetoothNoticeNSLog(@"设备连接断开原因:%@",error.localizedDescription);
        
        DTCDeviceModel *disconnectDevice = nil;
        for (NSUInteger i=0; i<weakSelf.scanDeviceList.count; i++) {
            DTCDeviceModel *device = weakSelf.scanDeviceList[i];
            if ([device.currentPeripheral isEqual:peripheral]) {
                disconnectDevice = device;
                [weakSelf.scanDeviceList removeObject:device];
                [weakSelf.connectedDeviceList removeObject:device];
                [weakSelf udpateDeviceCount];
            }
        }
        MAIN(^{
            [weakSelf deviceHasDisconnect:disconnectDevice];
            [weakSelf scanAroundDevice];
            if (disconnectDevice) {
                [weakSelf disconnectDevice:disconnectDevice];
            }
        });
    }];
    
    [_babyBluetooth setBlockOnFailToConnect:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
        [weakSelf deviceFailConnect:[weakSelf getDeviceModelByPeripheral:peripheral] error:error];
        BluetoothNoticeNSLog(@"设备:%@连接失败 外设的UUID:%@",[weakSelf getDeviceModelByPeripheral:peripheral].customName,peripheral.identifier.UUIDString);
        BluetoothNoticeNSLog(@"设备连接失败原因:%@",error.localizedDescription);
    }];
}

/*
 蓝牙设备回复
 */
- (void)sendDataToDeviceHandMessageBackHandle
{    
    __weak typeof(self) weakSelf = self;
    
    [_babyBluetooth setBlockOnDiscoverCharacteristics:^(CBPeripheral *peripheral, CBService *service, NSError *error) {
        
        for (CBCharacteristic *characteristic in service.characteristics) {
            BluetoothConnectDTNSLog(@"搜索到设备：%@ 设备service为:%@ 服务的CBCharacteristic为:%@",[weakSelf getDeviceModelByPeripheral:peripheral].customName,service.UUID.UUIDString,characteristic.UUID.UUIDString);
            if (characteristic.properties == CBCharacteristicPropertyNotify){
                [weakSelf.babyBluetooth notify:peripheral characteristic:characteristic block:^(CBPeripheral *peripheral, CBCharacteristic *characteristics, NSError *error) {
                    MAIN(^{
                        NSString *value = [NSString convertDataToHexStr:characteristics.value];
                        BluetoothAssistNoticeNSLog(@"********* ********* ***********");
                        BluetoothNoticeNSLog(@"-- >设备:%@ write回复:%@",[weakSelf getDeviceModelByPeripheral:peripheral].customName,value);
                        BluetoothAssistNoticeNSLog(@"********* ********* ***********");
                        
                        [weakSelf sendDataByWriteData:characteristic.value andNotifyCharacteristic:characteristic.UUID.UUIDString andDevice:[weakSelf getDeviceModelByPeripheral:peripheral]];
                    });
                }];
            }else if (characteristic.properties == CBCharacteristicPropertyRead){
                [peripheral readValueForCharacteristic:characteristic];
            }
        }
    }];
    
    //设置读取characteristics的委托
    [_babyBluetooth setBlockOnReadValueForCharacteristic:^(CBPeripheral *peripheral, CBCharacteristic *characteristics, NSError *error) {
        
        MAIN(^{
            NSString *value = [NSString convertDataToHexStr:characteristics.value];
            BluetoothAssistNoticeNSLog(@"********* ********* ***********");
            BluetoothNoticeNSLog(@"--> 设备:%@ read回复:%@",[weakSelf getDeviceModelByPeripheral:peripheral].customName,value);
            BluetoothAssistNoticeNSLog(@"********* ********* ***********");
            [weakSelf sendDataByReadData:characteristics.value andNotifyCharacteristic:characteristics.UUID.UUIDString andDevice:[weakSelf getDeviceModelByPeripheral:peripheral]];
        });
    }];
}

/*
 发送指令给设备
 */
- (void)sendValueToDeviceHandle
{
    __weak typeof(self) weakSelf = self;
    [_babyBluetooth setBlockOnDidWriteValueForCharacteristic:^(CBPeripheral *peripheral, CBCharacteristic *characteristic, NSError *error) {
        BluetoothAssistNoticeNSLog(@"--------- --------- -----------");
        BluetoothNoticeNSLog(@"手机发送指令给设备：%@ 指令内容为:%@",[weakSelf getDeviceModelByPeripheral:peripheral].customName,characteristic.value);
        BluetoothAssistNoticeNSLog(@"--------- --------- -----------");
    }];
}
/*
 蓝牙网关初始化和委托方法设置
 */
- (void)babyDelegate
{
    [self updateCentralManagerStateHandle];
    
    [self managerDiscoverPeripheralsHandle];
    
    [self connectToDeviceHandle];
    
    [self sendDataToDeviceHandMessageBackHandle];
    
    [self sendValueToDeviceHandle];
    
    [self connectDeviceSuccessHandle];
    
    [self disconnectDeviceSuccessHandle];
}

/*
 更新已经存在的外设
 */
- (BOOL) comparePeripheralisEqual :(CBPeripheral *)disCoverPeripheral RSSI:(NSNumber *)RSSI
{
    if ([self.scanDeviceList count] > 0) {
        
        for (int i = 0;i < [self.scanDeviceList count] ; i++) {
            
            DTCDeviceModel *device = [self.scanDeviceList objectAtIndex:i];
            
            if ([disCoverPeripheral isEqual:device.currentPeripheral]) {
                device.peripheralRSSI = RSSI;
                device.scanTime = time(NULL);
                return YES;
            }
        }
    }
    return NO;
}

/*
 根据外设查找对应的设备对象
 */
- (void)updateScanDeviceStatus
{
    if (self.scanDevice) {
        self.babyBluetooth.scanForPeripherals().begin();
    }else{
        [self.babyBluetooth cancelScan];
    }
}

- (DTCDeviceModel *)getDeviceModelByPeripheral:(CBPeripheral *)peripheral
{
    for (DTCDeviceModel *device in self.scanDeviceList) {
        if ([device.currentPeripheral isEqual:peripheral]) {
            return device;
        }
    }
    return nil;
}

- (void)sendDataByWriteData:(NSData *)data andNotifyCharacteristic:(NSString *)characterName andDevice:(DTCDeviceModel *)model
{
    if (self.delegate) {
        [self.delegate dtcBluetoothManagerWriteDataBack:data andNotifyCharacteristic:characterName sendByDevice:model];
    }
}

- (void)sendDataByReadData:(NSData *)data andNotifyCharacteristic:(NSString *)characterValue andDevice:(DTCDeviceModel *)model
{
    if (self.delegate) {
        [self.delegate dtcBluetoothManagerReadDataBack:data andNotifyCharacteristic:characterValue sendByDevice:model];
    }
}

- (void)udpateDeviceCount
{
    if (self.delegate) {
        [self.delegate dtcBluetoothManagerSearchDeviceChange:self.scanDeviceList];
    }
}

- (void)deviceHasDisconnect:(DTCDeviceModel *)device
{
    if (self.delegate) {
        [self.delegate dtcBluetoothManagerDisConnectByDevice:device];
    }
}

- (void)deviceHasConnect:(DTCDeviceModel *)device
{
    if (self.delegate) {
        [self.delegate dtcBluetoothManagerConnectSuccessByDevice:device];
    }
}

- (void)updateCentralManagerState:(CBManagerState)state
{
    if (self.delegate) {
        [self.delegate dtcBluetoothManagerCentralManagerState:state];
    }
}

- (void)deviceFailConnect:(DTCDeviceModel *)device error:(NSError *)error
{
    if (self.delegate) {
        [self.delegate dtcBluetoothManagerConnectFailByDevice:device error:error];
    }
}

- (void)deviceFindCharacteristic:(DTCDeviceModel *)deviceModel characeristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    if (self.delegate) {
        [self.delegate dtcBluetoothManagerDiscoverCharacteristicSerice:deviceModel characeristic:characteristic error:error];
    }
}
@end
